package com.example.teacher;

import android.util.Log;

import com.orhanobut.hawk.Hawk;

import org.json.JSONException;
import org.json.JSONObject;
import org.webrtc.IceCandidate;
import org.webrtc.PeerConnection;
import org.webrtc.SessionDescription;

import java.net.URISyntaxException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import io.socket.client.Ack;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;

/**
 * Created by chao on 2019/1/30.
 */

public class SignalingClient {
    private static final String TAG = "SignalingClient";
    private static SignalingClient instance;
    private String userId;
    private List<String>stringList=new ArrayList<>();
    private List<String>stringKey=new ArrayList<>();
 //  private List<HashMap<String ,PeerConnection  >>hashMapList=new ArrayList<>();
   private List<PeerConnection>peerConnectionList=new ArrayList<>();
  private  boolean meIsInfirst=false;
    private SignalingClient(){}
    public static SignalingClient get() {
        if(instance == null) {
            synchronized (SignalingClient.class) {
                if(instance == null) {
                    instance = new SignalingClient();
                }
            }
        }
        return instance;
    }

    private Socket socket;
    private String room = "roomid1";
    private Callback callback;


    private final TrustManager[] trustAll = new TrustManager[]{
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }
    };

    public void init(Callback callback) {
        this.callback = callback;
           /* SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAll, null);
            IO.setDefaultHostnameVerifier((hostname, session) -> true);
            IO.setDefaultSSLContext(sslContext);*/
            IO.Options opts = new IO.Options();
            opts.forceNew = false;
            opts.reconnection = true;
            opts.reconnectionDelay = 2000;      //延迟
            opts.reconnectionDelayMax = 6000;
            opts.reconnectionAttempts = -1;
            opts.timeout = 6000;
            if (socket == null) {
                try {
                    socket = IO.socket("http://42.192.180.207:3001",opts);
                    socket.connect();
                    addHandles();
                } catch (URISyntaxException e) {
                    e.printStackTrace();
                }
            }
           /* socket = IO.socket("http://192.168.8.141:3000",opts);*/
    /*    if (Hawk.contains("userId")){
            userId=Hawk.get("userId");

        }*/
        JSONObject data2 = new JSONObject();
        userId=UUIDUtil.get16UUID();
        try {
            data2.put("user_id", userId);//以socket id 作为 userId;
        } catch (JSONException e) {
            e.printStackTrace();
        }

        Log.d(TAG+"data2=", data2.toString()+"   =");

        socket.emit("join", "roomid1",data2);



            socket.on("full", args -> {
                Log.e(TAG+"chao", "room full");
            });

        // 其他用户加入通知
            socket.on("join", args -> {
                //Log.d("wthwhw",args[3]);
                UserInfo userInfo = new UserInfo();
                Log.d(TAG, "peer joined222 " + args[3].toString());
                stringList.clear();
              //  hashMapList.clear();
                stringKey.clear();
               String aa= args[3].toString().substring(1,args[3].toString().length()-1);

               String[]str=aa.split(",");
                for (int i=0;i<str.length;i++){
                    str[i].substring(1, str[i].length()-1);
                    stringList.add(str[i].substring(1, str[i].length()-1));
                }
                Log.d(TAG, "peer joined " + Arrays.toString(args));
                int num=Integer.valueOf(args[2].toString());
                //我先进入的布尔值
                if (num==1){
                    meIsInfirst=true;
                }
                if (num > 1) {
                    for (int i = 0; i < stringList.size(); i++) {
//                        HashMap<String ,Object> hashMap=new HashMap<>();
                        if (!userId.equals(stringList.get(i))) {
                            userInfo.setAccount(userId + "-" + stringList.get(i));
                            if (meIsInfirst){
                                //我先进来 拼接：我-别人
                                callback.CreatePeerConnnect(userId + "-" + stringList.get(i));//创建连接
                                stringKey.add(userId + "-" + stringList.get(i));

                            }else {
                                //我后进来 拼接：别人-我
                                callback.CreatePeerConnnect(stringList.get(i) + "-" + userId);//创建连接
                                stringKey.add(stringList.get(i) + "-" + userId);
                            }



//                            callback.onPeerJoined(userId+"-"+stringList.get(i));
                            Log.d(TAG, "peer joined拼接-- " + stringList.get(i) + "-" + userId);
                        }
                    }
//                        hashMap.put(stringList.get(i)+"-"+userId,PeerConnection);
                        /*if (!peerConnectionMap[userInfo.getAccount()] && !userId.equals(stringList.get(i))) {
                          //  createPeerConnecion(obj);
                            }
                        }*/
                    for (int m=0;m<stringKey.size();m++){
                        Log.d(TAG, "peer joined拼接--stringKey= " +stringKey.get(m));

                    }
                    if (userId.equals(args[4])) {
                        for(int i=0;i<stringKey.size();i++ ){
                            callback.onPeerJoined(stringKey.get(i));
                        }


                       /* Log.d(TAG, "peer joined拼接2222-- " + args[4] + "-" + userId);
                        callback.onPeerJoined(args[4] + "-" + userId);*/
                    }
                }
//                }else {

                  //  callback.CreatePeerConnnect(userId+"-"+userId);//创建连接

//                }
            });

     /*   socket.on("join", new Ack(){

            @Override
            public void call(Object... args) {

            }
        });*/


        socket.on("err", args -> {
            Log.d(TAG, "err= " + args[0]);
           // callback.onPeerJoined(String.valueOf(args[1]));
        });
       /* //监听事件:新用户加入通知
        socket.on("join", args -> {
            Log.d(TAG, "room created:" + socket.id());
            callback.onCreateRoom();
        });*/
            socket.on("joined", args -> {
                Log.d(TAG, "self joined:" + socket.id());
                callback.onSelfJoined();
            });
            socket.on("log", args -> {
                Log.d(TAG, "log call " + Arrays.toString(args));
            });
            socket.on("bye", args -> {
                Log.d("chao", "bye " + args[0]);
                callback.onPeerLeave((String) args[0]);
            });
        //主要是收到端对端的消息 进行处理
            socket.on("message", args -> {
                Object arg = args[1];
                if (arg instanceof String) {

                } else if (arg instanceof JSONObject) {
                    Log.d(TAG+"8888", "message " +  Arrays.toString(args));
                    JSONObject data = (JSONObject) arg;
                    JSONObject d = data.optJSONObject("data");
                    String type = d.optString("type");

                  /*  Log.d(TAG+"99", "message " +  d.optString("type"));
                    Log.d(TAG+"99", "message " +  d.optString("sdp"));
                    Log.d(TAG+"99", "message " +  d.optString("account"));*/

                    Log.d("JSONObject===", "bye==" + type);
                    if ("offer".equals(type)) {
                        callback.onOfferReceived(data);
                    } else if ("answer".equals(type)) {
                        callback.onAnswerReceived(data);
                    } else if ("candidate".equals(type)) {
                        callback.onIceCandidateReceived(data);
                    }
                }
            });
        }
    private  void addHandles() {
        /*
         * 断开连接
         * */
        socket.on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {

                Log.i(TAG, "连接断开");

            }
        });

        socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                Log.i(TAG, "连接中");


            }
        });

        socket.on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                Log.i(TAG, "连接失败=="+args[0].toString()+"===="+ args[0].hashCode());

            }
        });

        socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                Log.i(TAG, "连接成功");

            }
        });}
    public void destroy() {
       // socket.emit("bye", socket.id());
        socket.disconnect();
        socket.close();
        instance = null;
    }

    public void sendIceCandidate(IceCandidate iceCandidate, String to) {
        JSONObject jo = new JSONObject();
        JSONObject conten = new JSONObject();
        try {
            conten.put("type", "candidate");
            conten.put("label", iceCandidate.sdpMLineIndex);
            conten.put("id", iceCandidate.sdpMid);
            conten.put("candidate", iceCandidate.sdp);
           /* jo.put("from", socket.id());*/
            jo.putOpt("data",conten);
            jo.putOpt("account", to);
         //   Log.d("sdsdd",iceCandidate.sdp);
            socket.emit("message", room,jo);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    public void sendSessionDescription(SessionDescription sdp, String to) {
        JSONObject jo = new JSONObject();
        JSONObject conten = new JSONObject();
        try {
            conten.put("type", sdp.type.canonicalForm());
            conten.put("sdp", sdp.description);
            /* jo.put("from", socket.id());*/
            jo.putOpt("data",conten);
            jo.putOpt("account", to);

//            jo.put("type", sdp.type.canonicalForm());
//            jo.put("sdp", sdp.description);
//            jo.put("to", to);*/
            socket.emit("message", room,jo);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    public interface Callback {
        void onCreateRoom();
        void onPeerJoined(String socketId);
        void onSelfJoined();
        void onPeerLeave(String msg);

        void onOfferReceived(JSONObject data);
        void onAnswerReceived(JSONObject data);
        void onIceCandidateReceived(JSONObject data);
        void CreatePeerConnnect(String str);
    }

}
